package com_.dxy_test_.zookeeper_.distributed_lock_;

import com_.dxy_test_.redis_.RedisConfig;
import io.lettuce.core.api.sync.RedisCommands;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Description 锁测试
 * @Author dangxianyue
 * @Date 2022/11/8 17:27
 */
public class DLockTest implements Runnable {

    private static final int NUM = 20;//10并发线程
    private static final CountDownLatch CDL = new CountDownLatch(NUM);
    private static final String DECR_KEY = "dxy-decr-2";//商品数量
    private static final RedisCommands<String, String> syncCommands = RedisConfig.syncCommands;

//    private static Lock lock = new ReentrantLock();//JVM锁
//    private static Lock lock = RedisConfig.redissonClient.getLock("test_redis_lock");//Redis锁
    private static Lock lock = new MyZkLock("test_zk_lock");//Zookeeper锁

    public static void main(String[] args) throws Exception {

        //初始化limit
        syncCommands.set(DECR_KEY, "5");//初始化5个商品

        //模拟多应用实例到了一定时间才开始运行
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = formatter.parse("2022-11-09 16:36:50");
        long now;
        while ((now = System.currentTimeMillis()) < date.getTime()) {
//            System.out.println("now: " + now);
        }

        for (int i = 1; i <= NUM; i++) {
            new Thread(new DLockTest()).start();
            CDL.countDown();
        }
    }

    @Override
    public void run() {
        try {
            CDL.await();
            doBusiness();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void doBusiness() {

        //启动多个Main进程，模拟多个实例的场景下，JVM级别的锁不起作用，仍会超卖
        lock.lock();
        try {
            if (Long.parseLong(syncCommands.get(DECR_KEY)) > 0) {//商品数量，限制只卖5个
                Thread.sleep(80);//假设处理业务需要80毫秒
                Long decr = syncCommands.decr(DECR_KEY);
                System.out.println("卖出一个商品，剩余数量为：" + decr);
            } else {
                System.out.println("商品已卖完！");
            }
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
        finally {
            lock.unlock();
        }
    }
}
